package dbgorm

import (
	"errors"
	"fmt"
	"strings"
)

// 增强条数获取
func (c *DB) Counts() (int64, error) {
	var count int64
	err := c.Count(&count).Error
	return count, err
}

// When搜索
// 此搜索条件和gorm的where等同，最前方多了一层If bool的判断
//
//	when	判断注入的When条件，只有此处为true时才会注入后方的where条件
//	query	查询条件
//	args	附加参数
func (c *DB) When(when bool, query any, args ...any) *DB {
	if !when {
		return c
	}
	if query == "" {
		return c
	}
	if c == nil || c.DB == nil {
		return c
	}
	c.DB = c.DB.Where(query, args...)
	return c
}

// Between 范围检索
//
//	field	待检索的条件
//	start	开始条件
//	end		结束条件
func (db *DB) Between(field string, start, end any) *DB {
	if field == "" {
		return db
	}
	if db == nil || db.DB == nil {
		return db
	}
	db.DB = db.DB.Where(field+" BETWEEN ? AND ?", start, end)
	return db
}

// When Between 范围检索
//
//	when	判断注入的When条件，只有此处为true时才会注入后方的where条件
//	field	待检索的条件
//	start	开始条件
//	end		结束条件
func (db *DB) WhenBetween(when bool, field string, start, end any) *DB {
	if !when {
		return db
	}
	if field == "" {
		return db
	}
	if db == nil || db.DB == nil {
		return db
	}
	db.DB = db.DB.Where(field+" BETWEEN ? AND ?", start, end)
	return db
}

// 设置字段的范围信息
//
//	min_field	数据库中的最小ID/时间字段
//	max_field	数据库中的最大ID/时间字段
//	min			搜索的最小条件
//	max			搜索的最大条件
//	type_field	搜索模式，0-包含min和max 1-包含min，不包含max 2-包含max，不包含min 3-都不包含
func (db *DB) FieldMinMax(min_field, max_field string, min, max any, type_field uint8) *DB {
	if db == nil || db.DB == nil {
		return db
	}
	fids := []string{
		"( " + min_field + " > ? and " + max_field + " < ? )",
	}
	wheres := []any{
		min, max,
	}
	if type_field == 0 || type_field == 1 {
		// 包含min
		fids = append(fids, "( "+min_field+" <= ? AND "+max_field+" >= ? )")
		wheres = append(wheres, min, min)
	}
	if type_field == 0 || type_field == 2 {
		// 包含max
		fids = append(fids, "( "+min_field+" <= ? AND "+max_field+" >= ? )")
		wheres = append(wheres, max, max)
	}
	return db.Where(strings.Join(fids, " OR "), wheres...)
}

// 追加Likes搜索条件
//
//	fd	查询的字段【使用like进行匹配】
//	key	查询的字符串/数字等，请手动追加前后的%或者其他的%规则
//	op	查询条件，默认为 "LIKE ?"，可传入其他值，如：" = ?" / " > ? and  type = 1"......(字段在最前面，前后会追加括号，且仅第一个生效，所以写条件时需要注意位置)
func (c *DB) Likes(fd []string, key any, op ...string) *DB {
	if c == nil || c.DB == nil {
		return c
	}
	kkk := []any{}
	where_fields := []string{}
	tmp := "LIKE ?"
	if len(op) > 0 {
		tmp = op[0]
	}
	for i := 0; i < len(fd); i++ {
		where_fields = append(where_fields, fmt.Sprintf("( %s %s )", fd[i], tmp))
		kkk = append(kkk, key)
	}
	c.DB = c.DB.Where(strings.Join(where_fields, " OR "), kkk...)
	return c
}

// 搜索列表数据
//
//	offset	跳过条数
//	limit	查询条数
//	count	int64格式的条数搜索【需要为指针】
//	dest	搜索的字段列表【需要为指针】
func (c *DB) List(offset, limit int, count *int64, dest any) error {
	if c == nil {
		return errors.New("数据库未连接")
	}
	if c.DB == nil {
		return errors.New("数据库未连接")
	}
	db := c.DB
	err := db.Count(count).Error
	if err != nil {
		return err
	}
	err = db.Offset(offset).Limit(limit).Find(dest).Error
	if err != nil {
		return err
	}
	return nil
}
